#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include <FS.h>
#include <WiFiUdp.h>  // 添加UDP支持
#include "pages.h"
#include "func.h"  // 添加func.h头文件

const char* ssid = "";
const char* apSsid = "ESP8266-Access-Point";  // AP模式下的SSID
String wifiPassword = "wifi12345";  // WiFi连接密码，至少8个字符
String webPassword = "admin1234";   // 网页登录密码，至少8个字符
const char* configFile = "/config.json"; // 配置文件路径
const char* wolHistoryFile = "/wol_history.json"; // WOL历史记录文件路径

ESP8266WebServer server(80);

// 保存配置到文件
bool saveConfig() {
  File file = SPIFFS.open(configFile, "w");
  if (!file) {
    Serial.println("无法打开配置文件");
    return false;
  }

  StaticJsonDocument<256> doc;
  doc["ssid"] = ssid;
  doc["wifi_password"] = wifiPassword;
  doc["web_password"] = webPassword;
  
  if (serializeJson(doc, file) == 0) {
    Serial.println("保存配置文件失败");
    file.close();
    return false;
  }
  
  file.close();
  Serial.println("配置文件保存成功");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("WiFi密码: ");
  Serial.println(wifiPassword);
  return true;
}

// 从文件加载配置
bool loadConfig() {
  if (!SPIFFS.exists(configFile)) {
    Serial.println("配置文件不存在，将创建新文件");
    return saveConfig();
  }

  File file = SPIFFS.open(configFile, "r");
  if (!file) {
    Serial.println("无法打开配置文件");
    return false;
  }

  StaticJsonDocument<256> doc;
  DeserializationError error = deserializeJson(doc, file);
  if (error) {
    Serial.println("解析配置文件失败");
    file.close();
    return false;
  }

  if (doc.containsKey("ssid")) {
    ssid = strdup(doc["ssid"].as<const char*>());
  }
  
  if (doc.containsKey("wifi_password")) {
    wifiPassword = doc["wifi_password"].as<String>();
  }
  
  if (doc.containsKey("web_password")) {
    webPassword = doc["web_password"].as<String>();
  } else {
    webPassword = "admin1234"; // 设置默认网页密码
  }
  
  file.close();
  
  Serial.println("成功加载配置文件");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("WiFi密码: ");
  Serial.println(wifiPassword);
  Serial.print("网页密码: ");
  Serial.println(webPassword);
  
  return true;
}

void handleLogin() {
  Serial.println("Login request received");
  
  if (server.method() != HTTP_POST) {
    server.send(405, "text/plain", "Method Not Allowed");
    return;
  }

  if (!server.hasArg("password")) {
    server.send(400, "text/plain", "Missing password");
    return;
  }

  String inputPassword = server.arg("password");
  Serial.println("Input password: " + inputPassword);
  Serial.println("Stored web password: " + webPassword);

  if (inputPassword == webPassword) {
    server.send_P(200, "text/html", mainPage);
    Serial.println("Login successful");
  } else {
    server.send_P(401, "text/html", loginPage);
    Serial.println("Login failed");
  }
}

void handleWifiConfig() {
  if (server.method() == HTTP_GET) {
    server.send_P(200, "text/html", wifiConfigPage);
    return;
  }

  if (!server.hasArg("ssid") || !server.hasArg("password")) {
    server.sendHeader("Location", "/wifi_config?status=error&message=Missing+SSID+or+password");
    server.send(302);
    return;
  }

  String newSSID = server.arg("ssid");
  String newPassword = server.arg("password");

  // 更新SSID和密码并保存
  ssid = strdup(newSSID.c_str());
  wifiPassword = newPassword;
  if (!saveConfig()) {
    server.sendHeader("Location", "/wifi_config?status=error&message=Failed+to+save+config");
    server.send(302);
    return;
  }

  // 尝试连接新WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(newSSID.c_str(), newPassword.c_str());

    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 40) { // 增加连接尝试次数
      delay(500);
      Serial.print(".");
      attempts++;
    }
    Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    // 关闭AP模式
    WiFi.softAPdisconnect(true);
    server.sendHeader("Location", "/wifi_config?status=success&message=Connected+successfully");
    server.send(302);
    Serial. print("Wifi连接成功：");
    Serial. println(WiFi.localIP());

    onWifiConnected();  // 调用WiFi连接成功后的处理函数
  } else {
    // 连接失败，恢复AP模式
    WiFi.mode(WIFI_AP);
    WiFi.softAP(ssid, wifiPassword);
    server.sendHeader("Location", "/wifi_config?status=error&message=Failed+to+connect");
    server.send(302);
  }
}

void handleChangePassword() {
  if (server.method() == HTTP_GET) {
    server.send_P(200, "text/html", changePasswordPage);
    return;
  }

  if (!server.hasArg("current_password") || 
      !server.hasArg("new_password") || 
      !server.hasArg("confirm_password")) {
    String errorResponse = FPSTR(errorPage);
    errorResponse.replace("%s", "缺少必要参数");
    server.send(400, "text/html", errorResponse);
    return;
  }

  String currentPassword = server.arg("current_password");
  String newPassword = server.arg("new_password");
  String confirmPassword = server.arg("confirm_password");

    if (currentPassword != webPassword) {
      String errorResponse = FPSTR(errorPage);
      errorResponse.replace("%s", "当前密码错误");
      server.send(401, "text/html", errorResponse);
      return;
    }

    if (newPassword != confirmPassword) {
      String errorResponse = FPSTR(errorPage);
      errorResponse.replace("%s", "新密码不匹配");
      server.send(400, "text/html", errorResponse);
      return;
    }

  // 更新密码并保存
  webPassword = newPassword;
  if (!saveConfig()) {
    String errorResponse = FPSTR(errorPage);
    errorResponse.replace("%s", "保存配置失败");
    server.send(500, "text/html", errorResponse);
    return;
  }

  Serial.println("密码修改成功");
  server.send(200, "text/html", FPSTR(successPage));
}

// 启动Web服务器
void handleReset() {
  Serial.println("收到重置请求");
  // 删除配置文件
  if (SPIFFS.exists(configFile)) {
    SPIFFS.remove(configFile);
    Serial.println("已删除配置文件");
  }
  
  // 发送成功响应
  server.send(200, "text/plain", "设备正在重置...");
  
  // 延迟重启
  delay(1000);
  ESP.restart();
}

// 发送WOL魔法包
void sendWOL(const char* mac) {
  uint8_t macBytes[6];
  sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 
         &macBytes[0], &macBytes[1], &macBytes[2],
         &macBytes[3], &macBytes[4], &macBytes[5]);

  uint8_t packet[102];
  
  // 前6个字节为0xFF
  for(int i = 0; i < 6; i++) {
    packet[i] = 0xFF;
  }
  
  // 后96个字节为目标MAC地址重复16次
  for(int i = 6; i < 102; i += 6) {
    memcpy(&packet[i], macBytes, 6);
  }

  // 通过UDP发送魔法包
  WiFiUDP udp;
  udp.beginPacket("255.255.255.255", 9); // 广播地址，端口9
  udp.write(packet, sizeof(packet));
  udp.endPacket();
}

// 保存WOL历史记录
bool saveWOLHistory(const String& mac, const String& hostname) {
  // 读取现有历史记录
  DynamicJsonDocument doc(1024);
  if (SPIFFS.exists(wolHistoryFile)) {
    File readFile = SPIFFS.open(wolHistoryFile, "r");
    if (readFile) {
      DeserializationError error = deserializeJson(doc, readFile);
      if (error) {
        Serial.println("解析历史记录失败，将创建新文件");
        doc.clear();
      }
      readFile.close();
    }
  }

  // 检查是否已存在相同MAC地址的记录
  bool found = false;
  for (JsonObject record : doc.as<JsonArray>()) {
    if (record["mac"].as<String>() == mac) {
      // 更新现有记录
      record["hostname"] = hostname;
      record["timestamp"] = millis();
      found = true;
      break;
    }
  }

  // 如果不存在则添加新记录
  if (!found) {
    JsonObject record = doc.createNestedObject();
    record["mac"] = mac;
    record["hostname"] = hostname;
    record["timestamp"] = millis();
  }

  // 写入文件
  File file = SPIFFS.open(wolHistoryFile, "w");
  if (!file) {
    Serial.println("无法打开WOL历史记录文件");
    return false;
  }

  if (serializeJson(doc, file) == 0) {
    Serial.println("保存WOL历史记录失败");
    file.close();
    return false;
  }
  
  file.close();
  return true;
}

// 获取WOL历史记录
void handleWOLHistory() {
  if (!SPIFFS.exists(wolHistoryFile)) {
    server.send(200, "application/json", "[]");
    return;
  }

  File file = SPIFFS.open(wolHistoryFile, "r");
  if (!file) {
    server.send(200, "application/json", "[]");
    return;
  }

  // 直接读取整个JSON数组
  String json = file.readString();
  file.close();
  
  // 验证JSON格式
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, json);
  if (error) {
    // 如果格式错误，删除文件并返回空数组
    SPIFFS.remove(wolHistoryFile);
    server.send(200, "application/json", "[]");
    return;
  }
  
  server.send(200, "application/json", json);
}

void handleWOL() {
  Serial.println("收到WOL请求");
  
  if (server.method() != HTTP_POST) {
    Serial.println("错误：请求方法不正确");
    server.send(405, "text/plain", "Method Not Allowed");
    return;
  }

  if (!server.hasArg("mac")) {
    Serial.println("错误：缺少MAC地址参数");
    server.send(400, "text/plain", "Missing MAC address");
    return;
  }

  String mac = server.arg("mac");
  String hostname = server.arg("hostname");
  mac.toUpperCase();
  Serial.println("接收到的MAC地址：" + mac);
  Serial.println("接收到的主机名：" + hostname);
  
  // 验证MAC地址格式
  if (mac.length() != 17 || 
      mac[2] != ':' || mac[5] != ':' || 
      mac[8] != ':' || mac[11] != ':' || 
      mac[14] != ':') {
    Serial.println("错误：MAC地址格式不正确");
    server.send(400, "text/plain", "Invalid MAC address format");
    return;
  }
  
  // 验证每个字符是否为有效的十六进制数字
  for (int i = 0; i < mac.length(); i++) {
    if (i % 3 == 2) continue; // 跳过冒号
    char c = mac[i];
    if (!((c >= '0' && c <= '9') || 
          (c >= 'A' && c <= 'F'))) {
      Serial.println("错误：MAC地址包含无效字符");
      server.send(400, "text/plain", "Invalid MAC address characters");
      return;
    }
  }

  Serial.println("MAC地址验证通过，准备发送WOL包");
  
  // 发送WOL包
  sendWOL(mac.c_str());
  Serial.println("WOL包已发送");

  // 保存历史记录
  if (!saveWOLHistory(mac, hostname)) {
    Serial.println("警告：保存WOL历史记录失败");
  }
  
  server.send(200, "text/plain", "WOL packet sent to " + mac);
  Serial.println("响应已发送");
}

void handleScan() {
  Serial.println("收到WiFi扫描请求");
  
  // 扫描WiFi网络
  int n = WiFi.scanNetworks();
  if (n == 0) {
    server.send(200, "application/json", "[]");
    return;
  }

  // 构建网络列表JSON
  String json = "[";
  for (int i = 0; i < n; ++i) {
    if (i > 0) json += ",";
    json += "{";
    json += "\"ssid\":\"" + WiFi.SSID(i) + "\","; 
    json += "\"rssi\":" + String(WiFi.RSSI(i));
    json += "}";
  }
  json += "]";

  server.send(200, "application/json", json);
}

void startWebServer() {
  // 设置服务器路由
  server.on("/", []() {
    server.send_P(200, "text/html", loginPage);
  });
  server.on("/login", HTTP_POST, handleLogin);
  server.on("/wifi_config", handleWifiConfig);
  server.on("/change_password", handleChangePassword);
  server.on("/reset", HTTP_POST, handleReset);
  server.on("/scan", handleScan);
  server.on("/wol", HTTP_GET, []() {
    server.send_P(200, "text/html", wolPage);
  });
  server.on("/wol", HTTP_POST, handleWOL);
  // 获取WOL历史记录
  server.on("/wol/history", handleWOLHistory);
  
  // 清除WOL历史记录
  server.on("/wol/history/clear", HTTP_POST, []() {
    Serial.println("收到清除历史记录请求");
    
    Serial.println("正在删除WOL历史记录文件...");
    if (SPIFFS.exists(wolHistoryFile)) {
      if (SPIFFS.remove(wolHistoryFile)) {
        Serial.println("成功删除历史记录文件");
        server.send(200, "text/plain", "History cleared");
        return;
      }
      Serial.println("删除历史记录文件失败");
    } else {
      Serial.println("历史记录文件不存在");
    }
    server.send(500, "text/plain", "Failed to clear history");
  });

  // 启动服务器
  server.begin();
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("HTTP服务器已启动");
    Serial.print("访问地址: http://");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("HTTP服务器以AP模式启动");
    Serial.print("连接WiFi: ");
    Serial.println(apSsid);
    Serial.print("然后访问: http://");
    Serial.println(WiFi.softAPIP());
    //Serial.println("登陆密码:admin1234");
  }
}
void led_state()
{
  // 更新LED状态
  static unsigned long lastLedChange = 0;
  unsigned long currentMillis = millis();

  if (WiFi.getMode() == WIFI_AP)
  {
    // AP模式：闪烁（2000ms间隔）
    if (currentMillis - lastLedChange >= 2000)
    {
      digitalWrite(D4, !digitalRead(D4));
      lastLedChange = currentMillis;
    }
  }
  else if (WiFi.status() == WL_CONNECTED)
  {
    // STA模式且已连接：常亮
    digitalWrite(D4, LOW);
  }
  else
  {
    // STA模式但未连接：关闭LED
    digitalWrite(D4, HIGH);
  }
}

void initHardware() {
  delay(3000); // 延迟启动方便调试
  Serial.begin(115200);
  
  // 初始化LED引脚
  pinMode(D4, OUTPUT);
  digitalWrite(D4, LOW);
}

bool initFileSystem() {
  if (!SPIFFS.begin()) {
    Serial.println("无法挂载文件系统");
    return false;
  }
  return true;
}

void printConfigInfo() {
  Serial.println("成功加载配置文件");
  Serial.print("WiFi密码: ");
  Serial.println(wifiPassword);
  Serial.print("网页密码: ");
  Serial.println(webPassword);
}

bool connectToSavedWiFi() {
  Serial.println("尝试连接保存的WiFi...");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("Password: ");
  Serial.println(wifiPassword);

  // 扫描可用网络
  Serial.println("扫描可用WiFi网络...");
  int n = WiFi.scanNetworks();
  if (n == 0) {
    Serial.println("未找到任何网络");
  } else {
    Serial.print("找到");
    Serial.print(n);
    Serial.println("个网络:");
    for (int i = 0; i < n; ++i) {
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(" dBm) ");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? "开放" : "加密");
    }
  }

  // 尝试连接
  WiFi.mode(WIFI_STA);
  int retryCount = 0;
  bool connected = false;
  
  while (!connected && retryCount < 3) {
    Serial.print("连接尝试 #");
    Serial.println(retryCount + 1);
    
    WiFi.begin(ssid, wifiPassword.c_str());
    
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 40) {
      delay(150);
      digitalWrite(D4, !digitalRead(D4));
      delay(150);
      Serial.print(".");
      attempts++;
      if (attempts % 10 == 0) {
        Serial.println();
        Serial.print("WiFi status: ");
        Serial.println(WiFi.status());
      }
    }
    
    if (WiFi.status() == WL_CONNECTED) {
      connected = true;
      break;
    }
    
    retryCount++;
    Serial.println("连接失败，等待1秒后重试...");
    delay(1000);
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n连接成功");
    Serial.print("IP地址: ");
    Serial.println(WiFi.localIP());
    return true;
  } else {
    Serial.println("\n连接失败，状态码: ");
    Serial.println(WiFi.status());
    return false;
  }
}

void startAPMode() {
  Serial.println("\n连接失败，启动AP模式");
  WiFi.mode(WIFI_AP);
  
  // 设置AP信道和最大连接数，使用全局AP SSID
  bool apStarted = WiFi.softAP(apSsid, NULL, 6, 0, 8);
  if (!apStarted) {
    Serial.println("无法启动AP模式，请检查硬件");
    return;
  }
  
  Serial.println("AP模式已启动");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("信道: ");
  Serial.println(WiFi.channel());
}

void setup() {
  // 初始化硬件
  initHardware();

  // 初始化文件系统
  if (!initFileSystem()) {
    return;
  }

  // 加载配置文件
  if (!loadConfig()) {
    Serial.println("使用默认配置");
  } else {
    printConfigInfo();
  }

  // 设置WiFi模式
  Serial.println("正在初始化WiFi...");
  
  // 尝试连接保存的WiFi
  if (WiFi.status() != WL_CONNECTED) {
    if (connectToSavedWiFi()) {
      startWebServer();
      onWifiConnected();  // 调用WiFi连接成功后的处理函数
      return;
    }
  }
  
  // 启动AP模式
  startAPMode();
  // 开启web服务
  startWebServer();
}


void loop() {
  server.handleClient();

  //LED状态显示
  led_state();
}
